home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 424_01 / ed_157 / load_key.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-26  |  16.1 KB  |  629 lines

  1. /*
  2.  * Copyright (C) 1992 by Rush Record
  3.  * Copyright (C) 1993 by Charles Sandmann (sandmann@clio.rice.edu)
  4.  * 
  5.  * This file is part of ED.
  6.  * 
  7.  * ED is free software; you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation.
  9.  * 
  10.  * ED is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  11.  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  12.  * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License along with ED
  15.  * (see the file COPYING).  If not, write to the Free Software Foundation, 675
  16.  * Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18. #include "opsys.h"
  19.  
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23.  
  24. #define MAXRECUR 8
  25.  
  26. #include "memory.h"
  27. #include "ctyp_dec.h"
  28. #include "rec.h"
  29. #include "window.h"
  30. #include "ed_dec.h"
  31. #include "key_dec.h"
  32.  
  33. typedef struct def_str *def_ptr;
  34. typedef struct def_str
  35. {
  36.     def_ptr next;    /* next keydef in list */
  37.     Schar value;    /* key value */
  38.     Char lstloaded;    /* flag that list of defined subkeys is correct */
  39.     Int length;    /* length of definition */
  40.     Schar *values;    /* string of subkeys */
  41.     Char *deflst;    /* string of key-is-defined flags */
  42.     Int *repeats;    /* repeat counts for subkeys */
  43. } def_node;
  44.  
  45. static Int forgiven = 0;
  46. static def_ptr base = 0,last = 0;
  47. static Int level = -1;
  48. static def_ptr def[MAXRECUR];
  49. static Schar *byt[MAXRECUR];
  50. static Char *isdef[MAXRECUR];
  51. static Int *cnt[MAXRECUR];
  52. static Int remain[MAXRECUR];
  53. static Int repeat[MAXRECUR];
  54.  
  55. static Schar *defbuf;    /* these are used while defining keys */
  56. static Int *rptbuf;
  57. static Int defcount = 0;    /* count of keys in definition */
  58. static Int defining = -1;    /* which window has the "Defining key..." message, or -1 if no definition is in progress */
  59. static Schar defvalue;    /* key being defined */
  60. static Char ignore = 0;    /* flag to prevent evolution when user presses key that is to be defined */
  61. static Char abortkey = 0;    /* for aborting key evolution when bad condition obtains */
  62. static Char ignorealpha = 0;    /* flag to prevent evolution of alpha keys */
  63. static Char has_been_putoff = 0;    /* flag that putoff() was called */
  64.  
  65. extern Char *window_title();
  66.  
  67. /******************************************************************************\
  68. |Routine: was_putoff
  69. |Callby: init_term
  70. |Purpose: Checks whether we have to redisplay because we had called putoff();
  71. |Arguments:
  72. |    none
  73. \******************************************************************************/
  74. Int was_putoff()
  75. {
  76.     if(has_been_putoff)
  77.     {
  78.         has_been_putoff = 0;
  79.         return(1);
  80.     }
  81.     return(0);
  82. }
  83.  
  84. /******************************************************************************\
  85. |Routine: unload_key
  86. |Callby: load_key
  87. |Purpose: Removes a key definition from the key database.
  88. |Arguments:
  89. |    value is the value of the key to toss.
  90. \******************************************************************************/
  91. void unload_key(value)
  92. Schar value;
  93. {
  94.     def_ptr d,l;
  95.  
  96.     l = (def_ptr)&base;
  97.     for(d = base;d;l = d,d = d->next)
  98.         if(d->value == value)
  99.         {
  100.             l->next = d->next;
  101.             for(last = l;last->next;last = last->next);
  102.             ifree(d->repeats);
  103.             ifree(d->values);
  104.             ifree(d->deflst);
  105.             ifree(d);
  106.             for(d = base;d;d = d->next)    /* clear all list-loaded flags */
  107.                 d->lstloaded = 0;
  108.             return;
  109.         }
  110. }
  111.  
  112. /******************************************************************************\
  113. |Routine: load_key
  114. |Callby: load_key restore_par
  115. |Purpose: Stores a sequence of characters and repeat counts as a key definition
  116. |         in the key database.
  117. |Arguments:
  118. |    value is the value of the key that has been defined.
  119. |    length is the number of character/repeat pairs in the definition.
  120. |    buf is the sequence of characters.
  121. |    rpt is the array of repeat counts.
  122. \******************************************************************************/
  123. void load_key(value,length,buf,rpt)
  124. Int value,length;
  125. Schar *buf;
  126. Int *rpt;
  127. {
  128.     register def_ptr new;
  129.  
  130. /* remove any existing definition for this key */
  131.     unload_key((Schar)value);
  132.     new = (def_ptr)imalloc(sizeof(def_node));
  133.     new->values = (Schar *)imalloc(length);
  134.     new->deflst = (Char *)imalloc(length);
  135.     new->repeats = (Int *)imalloc(length * sizeof(Int));
  136.     memcpy((Char *)new->values,(Char *)buf,length);
  137.     memcpy(new->repeats,rpt,length * sizeof(Int));
  138.     new->length = length;
  139.     new->value = value;
  140.     if(!base)
  141.         base = new;
  142.     else
  143.         last->next = new;
  144.     new->next = 0;
  145.     last = new;
  146.     for(new = base;new;new = new->next)    /* clear all list-loaded flags */
  147.         new->lstloaded = 0;
  148. }
  149.  
  150. /******************************************************************************\
  151. |Routine: defined_key
  152. |Callby: init_term load_key
  153. |Purpose: Tests whether a key has a definition associated with it. Returns 1
  154. |         if the key is defined, else 0. Also stores the repeat count
  155. |         associated with the key so it can start evolving.
  156. |Arguments:
  157. |    value is the key we are testing.
  158. |    rept is the repeat count that was applied to the key when it was pressed
  159. |            (or when it was retrieved from another key definition).
  160. \******************************************************************************/
  161. Int defined_key(value,rept)
  162. Schar value;
  163. Int rept;
  164. {
  165.     register Schar *p;
  166.     register Char *q;
  167.     register def_ptr d,e;
  168.     register Int i;
  169.  
  170.     if(ignore)
  171.         return(0);
  172.     if(defining >= 0 && level < 0 && value != 11)
  173.     {
  174.         defbuf[defcount] = value;
  175.         rptbuf[defcount++] = rept;
  176.     }
  177.     if(level == MAXRECUR-1)
  178.         return(0);
  179.     if(!(value & 0x80))
  180.         if(isalpha(value))
  181.             if(ignorealpha || defining >= 0)
  182.                 return(0);
  183.     for(d = base;d;d = d->next)
  184.         if(d->value == value)    /* key is defined */
  185.         {
  186.             def[++level] = d;
  187.             repeat[level] = rept;
  188.             byt[level] = d->values;
  189.             isdef[level] = d->deflst;
  190.             if(!d->lstloaded)
  191.             {
  192.                 for(q = d->deflst,p = d->values,i = d->length;i--;p++,q++)    /* load the def list */
  193.                 {
  194.                     *q = 0;
  195.                     for(e = base;e;e = e->next)
  196.                         if(e->value == *p)
  197.                         {
  198.                             *q = 1;    /* this key in definition is itself defined */
  199.                             break;
  200.                         }
  201.                 }
  202.                 d->lstloaded = 1;
  203.             }
  204.             remain[level] = d->length;
  205.             cnt[level] = d->repeats;
  206.             if(!has_been_putoff && rept > 19)
  207.             {
  208.                 has_been_putoff = 1;
  209.                 putoff();
  210.             }
  211.             return(1);
  212.         }
  213.     return(0);
  214. }
  215.  
  216. /******************************************************************************\
  217. |Routine: next_key
  218. |Callby: init_term load_key
  219. |Purpose: Retrieves the next character/repeat pair in an evolving key. Returns
  220. |         0 if the definition has come to an end (or has been aborted), else 1.
  221. |Arguments:
  222. |    val is the returned key value.
  223. |    rept is the returned repeat count.
  224. \******************************************************************************/
  225. Int next_key(val,rept)
  226. Char *val;
  227. Int *rept;
  228. {
  229.     if(abortkey)
  230.     {
  231.         abortkey = 0;
  232.         level = -1;
  233.         return(0);
  234.     }
  235.     if(!remain[level]--)    /* if we are out of chars at the current level */
  236.         if(--repeat[level] <= 0)    /* if there are no more repetitions at this level */
  237.             return((--level < 0)? 0 : next_key(val,rept));    /* if at top level, fail, else recurse */
  238.         else    /* another repetition at this level */
  239.         {
  240.             byt[level] = def[level]->values;
  241.             isdef[level] = def[level]->deflst;
  242.             remain[level] = def[level]->length - 1;
  243.             cnt[level] = def[level]->repeats;
  244.         }
  245.     *val = *byt[level]++;    /* return next char */
  246.     *rept = *cnt[level]++;
  247.     if(!has_been_putoff && *rept > 19)
  248.     {
  249.         has_been_putoff = 1;
  250.         putoff();
  251.     }
  252.     if(!isalpha(*val) || *val & 0x80)    /* prevent recursion for alpha keys */
  253.         if(isdef[level][byt[level] - def[level]->values - 1])
  254.             if(defined_key(*val,*rept))
  255.                 next_key(val,rept);
  256.     return(1);
  257. }
  258.  
  259. /******************************************************************************\
  260. |Routine: define_key
  261. |Callby: edit inquire
  262. |Purpose: Handles creation of new key definitions. Called when they press ^K.
  263. |Arguments:
  264. |    none
  265. \******************************************************************************/
  266. void define_key()
  267. {
  268.     Int i;
  269.     Char buf[512];
  270.     
  271. /* if definition is in progress, terminate definition */
  272.     if(defining >= 0)
  273.     {
  274.         unload_key(defvalue);
  275.         if(defcount)
  276.             load_key(defvalue,defcount,defbuf,rptbuf);
  277.         ifree(rptbuf);
  278.         ifree(defbuf);
  279.         ignorealpha = 0;
  280.         move(WINDOW[defining].toprow - 1,1);    /* redisplay the file name */
  281.         ers_end();
  282.         reverse();
  283.         i = defining;
  284.         defining = -1;    /* this must be set first */
  285.         putz(window_title(i));
  286.         normal();
  287.         move(CURROW,CURCOL);
  288.         return;
  289.     }
  290.     move(WINDOW[0].toprow - 1,1);    /* CURWINDOW is bad if window is closed! */
  291.     ers_end();
  292.     reverse();
  293.     putz("Press the key you want to define.");
  294.     normal();
  295.     move(CURROW,CURCOL);
  296. /* start new definition */
  297.     ignore = 1;
  298.     get_next_key(&defvalue);
  299.     ignore = 0;
  300.     if(defvalue == 11)
  301.     {
  302.         move(WINDOW[0].toprow - 1,1);    /* redisplay the file name */
  303.         ers_end();
  304.         reverse();
  305.         putz(window_title(0));
  306.         normal();
  307.         move(CURROW,CURCOL);
  308.         return;
  309.     }
  310.     move(WINDOW[0].toprow - 1,1);
  311.     ers_end();
  312.     reverse();
  313.     sprintf(buf,"Defining key '%s'...",keyname[defvalue + 128]);
  314.     putz(buf);
  315.     normal();
  316.     move(CURROW,CURCOL);
  317.     defining = 0;
  318.     ignorealpha = 1;
  319.     defbuf = (Schar *)imalloc(4096);
  320.     rptbuf = (Int *)imalloc(4096*sizeof(int));
  321.     defcount = 0;
  322. }
  323.  
  324. /******************************************************************************\
  325. |Routine: store_keys
  326. |Callby: store_param
  327. |Purpose: Stores all key definitions in the user's startup file.
  328. |Arguments:
  329. |    fp is the startup file pointer.
  330. \******************************************************************************/
  331. void store_keys(fp)
  332. FILE *fp;
  333. {
  334.     Int n,pos;
  335.     def_ptr d;
  336.     Char buf[128];
  337.  
  338.     for(n = 0,d = base;d;d = d->next)
  339.         n++;
  340.     fprintf(fp,"ndefined=%d\n",n);
  341.     for(pos = 0,d = base;d;d = d->next)
  342.     {
  343.         sprintf(buf,"%x ",((int)d->value) & 0xff);
  344.         fputs(buf,fp);
  345.         pos += strlen(buf);
  346.         sprintf(buf,"%d ",d->length);
  347.         fputs(buf,fp);
  348.         pos += strlen(buf);
  349.         for(n = 0;n < d->length;n++)
  350.         {
  351.             sprintf(buf,"%x %x ",((int)d->values[n]) & 0xff,d->repeats[n]);
  352.             fputs(buf,fp);
  353.             if((pos += strlen(buf)) > 80)
  354.             {
  355.                 fprintf(fp,"\n");
  356.                 pos = 0;
  357.             }
  358.         }
  359.     }
  360.     if(pos)
  361.         fprintf(fp,"\n");
  362. }
  363.  
  364. /******************************************************************************\
  365. |Routine: definition_inprog
  366. |Callby: inquire ref_window
  367. |Purpose: Tests whether a key is currently being defined. Returns the window
  368. |         in which the "Defining key..." message appears, or -1 if no definition
  369. |         is in progress.
  370. |Arguments:
  371. |    none
  372. \******************************************************************************/
  373. Int definition_inprog()
  374. {
  375.     return(defining);
  376. }
  377.  
  378. /******************************************************************************\
  379. |Routine: abort_key
  380. |Callby: command copier down_arrow edit killer left_arrow move_eol move_word right_arrow up_arrow wincom
  381. |Purpose: Flags a condition that should make key definitions stop evolving. This
  382. |         would typically be a failed search, an attempt to move off the ends of
  383. |         the window, or an attempt to kill off the end of the window.
  384. |Arguments:
  385. |    none
  386. \******************************************************************************/
  387. void abort_key()
  388. {
  389.     if(!forgiven)
  390.         if(level >= 0)    /* ignore unless key is in progress */
  391.             abortkey = 1;
  392. }
  393.  
  394. /******************************************************************************\
  395. |Routine: ignore_alpha
  396. |Callby: inquire
  397. |Purpose: Prevents evolution of alpha keys. This is helpful when getting search
  398. |         strings and the like.
  399. |Arguments:
  400. |    none
  401. \******************************************************************************/
  402. void ignore_alpha()    /* prevent alpha evolution */
  403. {
  404.     ignorealpha = 1;
  405. }
  406.  
  407.  
  408. /******************************************************************************\
  409. |Routine: see_alpha
  410. |Callby: inquire
  411. |Purpose: Reestablishes evolution of alpha keys. Converse of ignore_alpha.
  412. |Arguments:
  413. |    none
  414. \******************************************************************************/
  415. void see_alpha()
  416. {
  417.     ignorealpha = 0;
  418. }
  419.  
  420. /******************************************************************************\
  421. |Routine: forgive
  422. |Callby: edit
  423. |Purpose: Can't remember.
  424. |Arguments:
  425. |    none
  426. \******************************************************************************/
  427. void forgive()
  428. {
  429.     forgiven = 1;
  430. }
  431.  
  432. /******************************************************************************\
  433. |Routine: begrudge
  434. |Callby: edit
  435. |Purpose: Can't remember.
  436. |Arguments:
  437. |    none
  438. \******************************************************************************/
  439. void begrudge()
  440. {
  441.     forgiven = 0;
  442. }
  443.  
  444. /******************************************************************************\
  445. |Routine: unload_defs
  446. |Callby: command
  447. |Purpose: Unloads all key definitions to a def file.
  448. |Arguments:
  449. |    none
  450. \******************************************************************************/
  451. void unload_defs(file)
  452. Char *file;
  453. {
  454.     FILE *fp;
  455.     Int n,pos,val,ind;
  456.     def_ptr d;
  457.     Char buf[128],buf2[128];
  458.  
  459.     if((fp = fopen(file,"w")))
  460.     {
  461.         for(d = base;d;d = d->next)
  462.         {
  463.             val = ((int)d->value) + 128;
  464.             sprintf(buf,"key:%s =",keyname[val]);
  465.             fputs(buf,fp);
  466.             pos = strlen(buf);
  467.             for(n = 0;n < d->length;n++)
  468.             {
  469.                 ind = ((int)d->values[n]) + 128;
  470.                 sprintf(buf,"[%d]",d->repeats[n]);
  471.                 if(pos + 1 + strlen(buf) + strlen(keyname[ind]) > 80)
  472.                 {
  473.                     fprintf(fp,"\n        ");
  474.                     pos = 8;
  475.                 }
  476.                 sprintf(buf2," %s%s",buf,keyname[ind]);
  477.                 fputs(buf2,fp);
  478.                 pos += strlen(buf2);
  479.             }
  480.             fprintf(fp,"\n");
  481.         }
  482.         fclose(fp);
  483.     }
  484. }
  485.  
  486. /******************************************************************************\
  487. |Routine: load_defs
  488. |Callby: command
  489. |Purpose: Loads all key definitions from an unloaded def file. Returns the
  490. |         number of matching strings (should be 1) or -1 when the buffer
  491. |         empties.
  492. |Arguments:
  493. |    pp - the pointer in the user buffer.
  494. |    count - a flag indicating that a [n] count should be parsed.
  495. |    pv - the returned key value.
  496. |    pr - the returned repeat count.
  497. \******************************************************************************/
  498. Int get_keyval(pp,count,pv,pr)
  499. Char **pp;
  500. Int count;
  501. Int *pv;
  502. Int *pr;
  503. {
  504.     Char *p,hit[256],c;
  505.     Int i,j,hits;
  506.     
  507.     p = *pp;
  508.     if(*p == '\n' || *p == '\0')
  509.         return(-1);
  510.     while(*p == ' ')    /* skip blanks */
  511.         if(*++p == '\n')
  512.             return(-1);
  513.     if(count)
  514.     {
  515.         if(*p++ != '[')
  516.             return(0);
  517.         for(i = 0;(c = *p++) != ']';i = 10 * i + c - '0');    /* parse the repeat count */
  518.         *pr = i;
  519.     }
  520.     memset(hit,1,sizeof(hit));    /* set hit list */
  521.     hits = 256;
  522.     i = 0;    /* column number in keyname array */
  523.     while(1)
  524.     {
  525.         if((c = *p++) == ' ')
  526.             c = 0;
  527.         else if(c == '\n')
  528.             c = 0;
  529.         for(j = 0;j < 256;j++)
  530.             if(hit[j])
  531.                 if(c != keyname[j][i])
  532.                 {
  533.                     hit[j] = 0;
  534.                     hits--;
  535.                 }
  536.         if(!c)
  537.             break;
  538.         i++;
  539.     }
  540.     if(hits == 1)
  541.     {
  542.         for(i = 0;i < 256;i++)
  543.             if(hit[i])
  544.                 break;
  545.         *pv = i - 128;
  546.     }
  547.     *pp = p;
  548.     return(hits);
  549. }
  550.  
  551. /******************************************************************************\
  552. |Routine: load_defs
  553. |Callby: command
  554. |Purpose: Loads all key definitions from an unloaded def file.
  555. |Arguments:
  556. |    none
  557. \******************************************************************************/
  558. void load_defs(file)
  559. Char *file;
  560. {
  561.     FILE *fp;
  562.     Schar keys[8192];
  563.     Char buf[2048],errorbuf[2048],*p,*q;    /* keys is signed char */
  564.     Int nkeys,value,val,rpt,i;
  565.     Int repeat[8192];
  566.     def_ptr d,n;
  567.     
  568.     if((fp = fopen(file,"r")))
  569.     {
  570.         for(d = base;d;d = n)    /* remove all defined keys */
  571.         {
  572.             n = d->next;
  573.             ifree(d->repeats);
  574.             ifree(d->values);
  575.             ifree(d->deflst);
  576.             ifree(d);
  577.         }
  578.         base = last = 0;
  579.         while(fgets(buf,sizeof(buf),fp))    /* read from file */
  580.         {
  581.             if(!strncmp(buf,"key:",4))    /* a new key starts */
  582.             {
  583. redo:
  584.                 q = p = buf + 4;
  585.                 i = get_keyval(&p,0,&value,&rpt);
  586.                 if(i != 1)
  587.                     goto error;
  588.                 while(*p == ' ' || *p == '=')
  589.                     p++;
  590.                 nkeys = 0;
  591. contin:
  592.                 while(1)
  593.                 {
  594.                     q = p;
  595.                     if((i = get_keyval(&p,1,&val,&rpt)) < 0)
  596.                         break;    /* get another line */
  597.                     if(i != 1)
  598.                         goto error;
  599.                     repeat[nkeys] = rpt;
  600.                     keys[nkeys++] = val;
  601.                 }
  602.                 if(!fgets(buf,sizeof(buf),fp))    /* end of file, complete def */
  603.                 {
  604.                     load_key(value,nkeys,keys,repeat);
  605.                     break;
  606.                 }
  607.                 if(!strncmp(buf,"key:",4))    /* new key starts, complete def and redo  */
  608.                 {
  609.                     load_key(value,nkeys,keys,repeat);
  610.                     goto redo;
  611.                 }
  612.                 p = buf;
  613.                 goto contin;
  614.             }
  615.         }
  616.         fclose(fp);
  617.     }
  618.     return;
  619. error:
  620.     fclose(fp);
  621.     if(!i)
  622.         sprintf(errorbuf,"Unrecognized key name:%s",q);
  623.     else if(i > 1)
  624.         sprintf(errorbuf,"Ambiguous key name:%s",q);
  625.     slip_message(errorbuf);
  626.     wait_message();
  627. }
  628.  
  629.